package me.zhengjie.modules.security.service

import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import me.zhengjie.common.utils.*
import me.zhengjie.common.utils.FileUtil.downloadExcel
import me.zhengjie.logging.slf4j.logError
import me.zhengjie.modules.security.config.bean.SecurityProperties
import me.zhengjie.modules.security.security.TokenProvider
import me.zhengjie.modules.security.service.dto.JwtUserDto
import me.zhengjie.modules.security.service.dto.OnlineUserDto
import org.springframework.data.domain.Pageable
import org.springframework.scheduling.annotation.Async
import org.springframework.stereotype.Service
import java.io.IOException
import java.util.*
import java.util.concurrent.TimeUnit

/**
 * @author Kuki Wu
 * @Date 2019年10月26日21:56:27
 */
@Service
class OnlineUserService(
    private val properties: SecurityProperties,
    private val tokenProvider: TokenProvider,
    private val redisUtils: RedisUtil
) {
    /**
     * 保存在线用户信息
     * @param jwtUserDto /
     * @param token /
     * @param request /
     */
    fun save(jwtUserDto: JwtUserDto, token: String?, request: HttpServletRequest?) {
        val dept: String = jwtUserDto.user!!.userDTO!!.dept!!.name!!
        val ip = StringUtils.getIp(request)
        val browser = StringUtils.getBrowser(request)
        val address = StringUtils.getCityInfo(ip)
        var onlineUserDto: OnlineUserDto? = null
        try {
            onlineUserDto = OnlineUserDto(
                jwtUserDto.username,
                jwtUserDto.user!!.userDTO!!.nickName!!,
                dept,
                browser,
                ip,
                address,
                EncryptUtils.desEncrypt(token),
                Date()
            )
        } catch (e: java.lang.Exception) {
            logError(e.message!!)
        }
        val loginKey: String = tokenProvider.loginKey(token)
        redisUtils.set(loginKey, onlineUserDto!!, properties.tokenValidityInSeconds!!, TimeUnit.MILLISECONDS)
    }

    /**
     * 查询全部数据
     * @param username /
     * @param pageable /
     * @return /
     */
    fun getAll(username: String, pageable: Pageable): PageResult<OnlineUserDto> {
        val onlineUserDtos = getAll(username)
        val pagedOnlineUserDtos = PageUtil.paging(pageable.pageNumber, pageable.pageSize, onlineUserDtos)
        return PageUtil.toPage(pagedOnlineUserDtos, onlineUserDtos.size.toLong()) as PageResult<OnlineUserDto>
    }

    /**
     * 查询全部数据，不分页
     * @param username /
     * @return /
     */

    fun getAll(username: String): List<OnlineUserDto> {
        val loginKey = properties.onlineKey + if (org.apache.commons.lang3.StringUtils.isEmpty(username)) "" else "*$username"
        val keys = redisUtils.scan("$loginKey*")
        val onlineUserDtos = keys.reversed().map { redisUtils.get(it) as OnlineUserDto }
        return onlineUserDtos.sortedByDescending { it.loginTime }
    }


    @Async
    fun kickOutForUsername(username: String) {
        val loginKey: String = properties!!.onlineKey + username + "*"
        //redisTemplate.delete(loginKey)
        redisUtils.scanDel(loginKey)
    }

    /**
     * 退出登录
     * @param token /
     */
    fun logout(token: String?) {
        val loginKey = tokenProvider.loginKey(token)
        redisUtils.del(loginKey)
    }

    /**
     * 查询用户
     * @param key /
     * @return /
     */
    fun getOne(key: String?): OnlineUserDto? {
        return redisUtils.get(key!!) as OnlineUserDto?
    }

    @Throws(IOException::class)
    fun download(all: List<OnlineUserDto?>, response: HttpServletResponse?) {
        val list: MutableList<Map<String?, Any?>?> = ArrayList()
        for (user in all) {
            val map: MutableMap<String?, Any?> = LinkedHashMap()
            map["用户名"] = user!!.userName
            map["部门"] = user.dept
            map["登录IP"] = user.ip
            map["登录地点"] = user.address
            map["浏览器"] = user.browser
            map["登录日期"] = user.loginTime
            list.add(map)
        }
        downloadExcel(list, response!!)
    }
}